//#include <stdlib.h>
#include <iostream>

#define EXAMPLE2

using namespace std;

#ifdef EXAMPLE1
// Purpose.  Proxy design pattern
class RealImage
{
private:
    int m_id;

public:
    RealImage(int id)
    {
        this->m_id = id;
        cout << "ctor: " << id << endl;
    }

    ~RealImage()
    {
        cout << "dtor: " << m_id << endl;
    }

    void draw()
    {
        cout << "drawing image " << m_id << endl;
    }
};

class Image
{
private:
    int m_id;
    static int s_next;
    RealImage *pTheRealThing;

public:
    Image()
    {
        m_id = s_next++;
        pTheRealThing = NULL;
    }

    ~Image()
    {
        delete pTheRealThing;
    }

    void draw()
    {
        if (!pTheRealThing)
            pTheRealThing = new RealImage(m_id);
        pTheRealThing->draw();
    }
};

int Image::s_next = 1;

#else
// Purpose.  "->" and "." operators give different results
class Subject
{
public:
    virtual void execute() = 0;
};

class RealSubject : Subject
{
private:
    string m_str;

public:
    RealSubject(string str)
    {
        m_str = str;
    }

    void execute()
    {
        cout << m_str << endl;
    }
};

class ProxySubject : Subject
{
private:
    string m_first, m_second, m_third;
    RealSubject *m_pRealSubject;

public:
    ProxySubject(string s)
    {
        int num = s.find_first_of(' ');
        m_first = s.substr(0, num);
        s = s.substr(num + 1);

        num = s.find_first_of(' ');
        m_second = s.substr(0, num);
        s = s.substr(num + 1);

        num = s.find_first_of(' ');
        m_third = s.substr(0, num);
        s = s.substr(num + 1);

        m_pRealSubject = new RealSubject(s);
    }

    ~ProxySubject()
    {
        delete m_pRealSubject;
    }

    RealSubject* operator->()
    {
        cout << m_first << " " << m_second << " ";
        return m_pRealSubject;
    }

    void execute()
    {
        cout << m_first << " " << m_third << " ";
        m_pRealSubject->execute();
    }
};
#endif

int main(int argc, char** argv)
{
#ifdef EXAMPLE1
    Image images[5];
    int i;

    cout << "Exit[0], Image[1-5]: ";
    cin >> i;
    while (i)
    {
        images[i-1].draw();
        cout << "Exit[0], Image[1-5]: ";
        cin >> i;
    }
#else // Example 2
    ProxySubject obj(string("the quick brown fox jumped over the dog"));
    obj->execute();
    obj.execute();
#endif
    return (EXIT_SUCCESS);
}

